package com.hudson.core.concurrent.threadpool;


import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

public class TimerThreadPool extends ThreadPoolExecutor implements TimerThreadPoolSpec {
    private String poolName;
    private WatchList<Long> timerList;

    public TimerThreadPool(String poolName, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, WatchList<Long> timerList) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
        this.poolName = poolName;
        this.timerList = new WatchList<>();
    }

    public TimerThreadPool(String poolName, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
        this.poolName = poolName;
        this.timerList = new WatchList<>();
    }

    @Override
    public Map<String, Object> getWatchDate() {
        Map<String, Object> result = new HashMap<>();
        result.put("pollSize", getPoolSize());
        result.put("activeCount", getActiveCount());
        result.put("taskCount", getTaskCount());
        result.put("completedTaskCount", getCompletedTaskCount());
        result.put("waitTask", getQueue().size());
        AtomicReference<Long> consumeTime = new AtomicReference<>(0L);
        try {
            timerList.call(() -> {
                consumeTime.set(timerList.list.stream().reduce(0L, Long::sum));
                timerList.list.clear();
                return consumeTime;
            });
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        result.put("consumeTime", consumeTime.get());
        return result;
    }

    public void execute(Runnable command){
        long startTime = System.currentTimeMillis();
        super.execute(command);
        timerList.add(System.currentTimeMillis() - startTime);
    }

    public void exec(Runnable task) {
        execute(() -> {
            long startTime = System.currentTimeMillis();
            task.run();
            timerList.add(System.currentTimeMillis() - startTime);
        });
    }


    public String getPoolName() {
        return poolName;
    }

    public void setPoolName(String poolName) {
        this.poolName = poolName;
    }


    public WatchList<Long> getTimerList() {
        return timerList;
    }

    public void setTimerList(WatchList<Long> timerList) {
        this.timerList = timerList;
    }
}
